# coding=utf-8
import sys

reload(sys)
sys.setdefaultencoding('utf8')
import pygame
from pygame.locals import *
import socket
import utils
import threading
import json

logger = utils.get_logger(__name__)


def set_window_location(x=50, y=50):
    """
    设置游戏窗口显示位置
    :param x: 横坐标
    :param y: 纵坐标
    :return:
    """
    import os
    os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x, y)


class Square(pygame.sprite.Sprite):
    """
    棋盘上的方格
    """

    def __init__(self, color=(255, 255, 255), size=(50, 50)):
        super(Square, self).__init__()
        self.image = pygame.Surface(size)
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.has_chees = False
        self.chees_color = 1

    def add_chees(self, chees_color=1):
        """
        添加棋子
        :param chees_color:棋子的颜色 1-黑色 -1-其他
        :return:
        """
        self.has_chees = True
        self.chees_color = chees_color

    def draw_chees(self):
        """
        在矩形上画出棋子
        :return:
        """
        self.image.fill((255, 255, 255))
        if self.has_chees:
            if self.chees_color == 1:
                color = (0, 0, 0)
            else:
                color = (0, 122, 34)
            pygame.draw.circle(self.image, color, (25, 25), 25)


class BeginBtn(pygame.sprite.Sprite):
    def __init__(self):
        super(BeginBtn, self).__init__()
        self.chees_running = False
        self.image = pygame.Surface((160, 80))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.topleft = (800, 200)

    def draw_text(self):
        self.image.fill((255, 255, 255))
        fontobj = pygame.font.SysFont('楷体', 22)
        if self.chees_running:
            text = u'结束本局游戏'
        else:
            text = u'开始游戏'
        text_surf_obj = fontobj.render(text, True, (0, 0, 0))
        text_rect_obj = text_surf_obj.get_rect()
        text_rect_obj.center = (80, 40)
        self.image.blit(text_surf_obj, text_rect_obj)


class GoBang(object):
    def __init__(self):
        set_window_location()
        pygame.init()
        self.chees_running = False
        self.winner = 0
        self.cheesboard_size = 15
        self.cheesboard = [[0 for i in range(self.cheesboard_size)] for j in range(self.cheesboard_size)]
        self.screen = pygame.display.set_mode((1000, 765))
        self.square_group = pygame.sprite.Group()
        self.get_square_group()
        self.set_square_pos()
        self.begin_btn = BeginBtn()
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.running = True
        self.mode = 2  # 1 人类对人类 2 机器对机器
        # 0-初始值 1-与服务器连接完成 2-等待接收服务器命令 3-接收服务器命令完成 4-等待执行命令 5-命令执行完成
        # 6-等待回应服务器 7-回应完成
        self.flag_ui_with_server = 0
        self.chees_x, self.chees_y = 0, 0
        self.start_gui()

    def start_gui(self):
        """
        启动gui程序
        :return:
        """
        if self.mode == 1:
            self.run_human_to_human()
        elif self.mode == 2:
            self.client_thread = threading.Thread(target=self.connect_server)
            self.client_thread.start()
            self.run_ai_to_ai()

    def connect_server(self):
        """
        与服务器进行连接
        :return:
        """
        logger.info(u'正在连接到服务器...')
        self.sp_text = u'正在连接到服务器...'
        self.client.connect(('127.0.0.1', 9887))
        logger.info(u'连接成功')
        self.sp_text = u'连接成功'
        logger.info(u'正在向服务器表明身份...')
        self.sp_text = u'正在向服务器表明身份...'
        self.client.send('ui-client')
        self.flag_ui_with_server = 1  # 连接完成
        self.flag_ui_with_server = 2  # 等待接收命令
        # 命令：start_game end_game add_chees
        while True:
            data = self.client.recv(1024)
            js_data = json.loads(data)
            if self.flag_ui_with_server == 2:  # 正在等待接收命令
                self.flag_ui_with_server = 3  # 接受完成
                self.flag_ui_with_server = 4  # 等待执行命令
                if js_data['command'] == 'start_game':  # 开始游戏
                    self.chees_x = js_data['data']['x']
                    self.chees_y = js_data['data']['y']
                    self.color = js_data['data']['color']
                    if self.flag_ui_with_server == 4:
                        self.init_new_game()
                        self.add_chees_ai_to_ai()
                        self.flag_ui_with_server = 5  # 命令执行完成
                        self.flag_ui_with_server = 6  # 等待返回消息
                        flag, who = self.check_winner()
                        return_data = {}
                        if flag:
                            return_data['status'] = 'win'
                            return_data['winner'] = who
                        elif self.check_tie():
                            return_data['status'] = 'tie'
                        else:
                            return_data['status'] = 'ok'
                        js_str = json.dumps(return_data)
                        self.client.send(js_str)
                        self.flag_ui_with_server = 7  # 返回消息完成
                        self.flag_ui_with_server = 2  # 等待接收数据
                elif js_data['command'] == 'end_game':  # 结束游戏
                    self.client.send('shutdown')
                    self.running = False
                    self.client.close()
                    return
                elif js_data['command'] == 'add_chees':  # 落子
                    self.chees_x = js_data['data']['x']
                    self.chees_y = js_data['data']['y']
                    self.color = js_data['data']['color']
                    if self.flag_ui_with_server == 4:
                        self.add_chees_ai_to_ai()
                        self.flag_ui_with_server = 5  # 命令执行完成
                        self.flag_ui_with_server = 6  # 等待返回消息
                        flag, who = self.check_winner()
                        return_data = {}
                        if flag:
                            return_data['status'] = 'win'
                            return_data['winner'] = who
                        elif self.check_tie():
                            return_data['status'] = 'tie'
                        else:
                            return_data['status'] = 'ok'
                        js_str = json.dumps(return_data)
                        self.client.send(js_str)
                        self.flag_ui_with_server = 7  # 返回消息完成
                        self.flag_ui_with_server = 2  # 等待接收数据

    def get_square_group(self):
        """
        生成方块列表
        :return:
        """
        for i in range(self.cheesboard_size):
            for j in range(self.cheesboard_size):
                squ = Square()
                self.square_group.add(squ)

    def set_square_pos(self):
        """
        设置方块的位置
        :return:
        """
        x = 0
        y = 0
        for square in self.square_group:
            square.rect.topleft = (x * 51, y * 51)
            y += 1
            if y % 15 == 0:
                x += 1
                y = 0

    def draw_sp_text(self):
        fontobj = pygame.font.SysFont('楷体', 22)
        text_surf_obj = fontobj.render(self.sp_text, True, (255, 255, 255))
        text_rect_obj = text_surf_obj.get_rect()
        text_rect_obj.center = (880, 100)
        self.screen.blit(text_surf_obj, text_rect_obj)

    def draw_text(self):
        fontobj = pygame.font.SysFont('楷体', 22)
        if self.chees_running:
            text = u'当前执子：{}'.format(u'黑子' if self.color == 1 else u'绿子')
        else:
            if self.winner == 0:
                text = u'欢迎进入游戏'
            elif self.winner == -1:
                text = u'黑子获胜！'
            else:
                text = u'绿子获胜！'
        text_surf_obj = fontobj.render(text, True, (255, 255, 255))
        text_rect_obj = text_surf_obj.get_rect()
        text_rect_obj.center = (880, 100)
        self.screen.blit(text_surf_obj, text_rect_obj)

    def print_cheesboard(self):
        """
        打印棋盘信息
        :return:
        """
        print '*' * 50
        ss = ''
        for i in range(self.cheesboard_size):
            for j in range(self.cheesboard_size):
                ss += '{} '.format(self.cheesboard[i][j])
            ss += '\n'
        print ss
        print '*' * 50

    def draw_screen(self):
        """
        重画屏幕
        :return:
        """
        self.screen.fill((0, 0, 0))
        self.draw_text()
        self.begin_btn.draw_text()
        self.screen.blit(self.begin_btn.image, self.begin_btn.rect)
        current_time = pygame.time.get_ticks()
        self.square_group.update(current_time)
        for square in self.square_group:
            square.draw_chees()
            self.screen.blit(square.image, square.rect)
        pygame.display.update()

    def draw_screen_ai_to_ai(self):
        """
        重画屏幕
        :return:
        """
        self.screen.fill((0, 0, 0))
        self.draw_sp_text()
        # self.begin_btn.draw_text()
        # self.screen.blit(self.begin_btn.image, self.begin_btn.rect)
        current_time = pygame.time.get_ticks()
        self.square_group.update(current_time)
        for square in self.square_group:
            square.draw_chees()
            self.screen.blit(square.image, square.rect)
        pygame.display.update()

    def deal_with_begin_btn(self):
        """
        处理开始/结束按钮的点击事件
        :return:
        """
        self.chees_running = not self.chees_running
        for square in self.square_group:
            square.has_chees = False
        self.begin_btn.chees_running = not self.begin_btn.chees_running
        self.cheesboard = [[0 for i in range(self.cheesboard_size)] for j in
                           range(self.cheesboard_size)]

    def init_new_game(self):
        """
        初始化一场游戏
        :return:
        """
        # 初始化棋盘方块
        for square in self.square_group:
            square.has_chees = False
        # 初始化棋盘数组
        self.cheesboard = [[0 for i in range(self.cheesboard_size)] for j in
                           range(self.cheesboard_size)]
        # 初始化回合数和提示信息
        self.hh_cnt = 1
        self.sp_text = u'当前回合：{}\n当前执子：{}'.format(self.hh_cnt, u'黑子' if self.color == 1 else u'绿子')

    def add_chees_ai_to_ai(self):
        """
        落子-ai对ai
        :return:
        """
        self.cheesboard[self.chees_x][self.chees_y] = self.color
        cnt = self.chees_x * self.cheesboard_size + self.chees_y
        current_cnt = 0
        for square in self.square_group:
            if current_cnt == cnt:
                square.add_chees(self.color)
                break
            current_cnt += 1
        self.hh_cnt += 1
        self.sp_text = u'当前回合：{}\n当前执子：{}'.format(self.hh_cnt, u'黑子' if self.color == -1 else u'绿子')

    def check_winner(self):
        """
        检查是否产生赢家
        :return: (是否产生赢家，赢家代数)
        """
        for i in range(self.cheesboard_size):
            for j in range(self.cheesboard_size):
                if self.cheesboard[i][j] == 0:
                    continue
                is_win = True
                if j + 4 < self.cheesboard_size:
                    for x in range(j + 1, j + 5):
                        if self.cheesboard[i][x] != self.cheesboard[i][j]:
                            is_win = False
                            break
                else:
                    is_win = False
                if is_win:
                    return True, self.cheesboard[i][j]
                is_win = True
                if i + 4 < self.cheesboard_size:
                    for x in range(i + 1, i + 5):
                        if self.cheesboard[x][j] != self.cheesboard[i][j]:
                            is_win = False
                            break
                else:
                    is_win = False
                if is_win:
                    return True, self.cheesboard[i][j]
                is_win = True
                if i + 4 < self.cheesboard_size and j + 4 < self.cheesboard_size:
                    for x in range(1, 5):
                        if self.cheesboard[i + x][j + x] != self.cheesboard[i][j]:
                            is_win = False
                            break
                else:
                    is_win = False
                if is_win:
                    return True, self.cheesboard[i][j]
                is_win = True
                if i + 4 < self.cheesboard_size and j - 4 > -1:
                    for x in range(1, 5):
                        if self.cheesboard[i + x][j - x] != self.cheesboard[i][j]:
                            is_win = False
                            break
                else:
                    is_win = False
                if is_win:
                    return True, self.cheesboard[i][j]
        return False, 0

    def check_tie(self):
        """
        检查是否产生平局
        :return: 是，True，否则，False
        """
        for i in self.cheesboard:
            for j in i:
                if j == 0:
                    return False
        return True

    def deal_with_winner(self):
        """
        检查是否产生赢家并做相应处理
        :return:
        """
        flag, winner = self.check_winner()
        if flag:
            self.winner = winner
            self.chees_running = not self.chees_running
            self.begin_btn.chees_running = not self.begin_btn.chees_running
            self.cheesboard = [[0 for i in range(self.cheesboard_size)] for j in
                               range(self.cheesboard_size)]

    def run_human_to_human(self):
        """
        人与人对弈
        :return:
        """
        self.color = 1
        while self.running:
            self.draw_screen()
            for event in pygame.event.get():
                # 按键
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.running = False
                # 退出
                elif event.type == QUIT:
                    self.running = False
                # 点击鼠标
                elif event.type == MOUSEBUTTONDOWN:
                    press_array = pygame.mouse.get_pressed()
                    if press_array[0]:
                        x, y = pygame.mouse.get_pos()
                        # 检测是否点击开始/结束按钮
                        if x >= 800 and x <= 960 and y >= 200 and y <= 280:
                            self.deal_with_begin_btn()
                        # 检测是否在下棋
                        if self.chees_running:
                            cnt = 0
                            for square in self.square_group:
                                square_x, square_y = square.rect.topleft
                                if x >= square_x and x <= square_x + 51 and y >= square_y and y <= square_y + 51:
                                    if square.has_chees:
                                        continue
                                    square.add_chees(self.color)
                                    self.color = -self.color
                                    pos_x = cnt / self.cheesboard_size
                                    pos_y = cnt % self.cheesboard_size
                                    self.cheesboard[pos_y][pos_x] = self.color
                                    self.deal_with_winner()
                                    break
                                cnt += 1

    def run_ai_to_ai(self):
        """
        运行棋盘程序
        :return:
        """
        self.color = 1
        while self.running:
            self.draw_screen_ai_to_ai()
            for event in pygame.event.get():
                # 按键
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.running = False
                # 退出
                elif event.type == QUIT:
                    self.running = False
                # 点击鼠标
                elif event.type == MOUSEBUTTONDOWN:
                    press_array = pygame.mouse.get_pressed()
                    if press_array[0]:
                        x, y = pygame.mouse.get_pos()
                        # 检测是否点击开始/结束按钮
                        if x >= 800 and x <= 960 and y >= 200 and y <= 280:
                            self.deal_with_begin_btn()

    def run(self):
        """
        运行棋盘程序
        :return:
        """
        self.color = 1
        while self.running:
            self.draw_screen()
            for event in pygame.event.get():
                # 按键
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.running = False
                # 退出
                elif event.type == QUIT:
                    self.running = False
                # 点击鼠标
                elif event.type == MOUSEBUTTONDOWN:
                    press_array = pygame.mouse.get_pressed()
                    if press_array[0]:
                        x, y = pygame.mouse.get_pos()
                        # 检测是否点击开始/结束按钮
                        if x >= 800 and x <= 960 and y >= 200 and y <= 280:
                            self.deal_with_begin_btn()
                        # 检测是否在下棋
                        if self.chees_running:
                            cnt = 0
                            for square in self.square_group:
                                square_x, square_y = square.rect.topleft
                                if x >= square_x and x <= square_x + 51 and y >= square_y and y <= square_y + 51:
                                    if square.has_chees:
                                        continue
                                    square.add_chees(self.color)
                                    self.color = -self.color
                                    pos_x = cnt / self.cheesboard_size
                                    pos_y = cnt % self.cheesboard_size
                                    self.cheesboard[pos_y][pos_x] = self.color
                                    self.deal_with_winner()
                                    break
                                cnt += 1


if __name__ == '__main__':
    GoBang()
